package br.com.virtual.cadastrar.model;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import br.com.virtual.base.enums.TipoPessoaEnum;
import br.com.virtual.base.listener.VirtualEntityListener;
import br.com.virtual.base.model.VirtualModel;
import br.com.virtual.recomendar.model.Avaliacao;
import br.com.virtual.vender.model.Interesse;

@Entity
@EntityListeners({ VirtualEntityListener.class })
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa extends VirtualModel implements Comparable<Pessoa> {

	private static final long serialVersionUID = 1L;

	@Id	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;	
	
	private String nome;
	
	@Column(unique = true, nullable = false)
	private String email;
	
	private String telefone1;
	
	private String telefone2;
	
	private boolean newsLetter;
	
	private boolean ativo = true;
	
	@Enumerated(EnumType.ORDINAL)
	private TipoPessoaEnum tipoPessoa = TipoPessoaEnum.FISICA;

	@OneToOne(cascade = CascadeType.REFRESH)
	private Usuario usuario;

	@OneToMany(mappedBy = "pessoa", cascade = CascadeType.REFRESH)
	private List<Endereco> enderecos;

	@OneToOne(cascade = CascadeType.REFRESH, fetch=FetchType.EAGER)
	private Interesse interesse;

	
	@OneToMany(mappedBy="pessoa")
	private List<Avaliacao> avaliacoes;

	
	
	public Pessoa(){}
	
	
	public Pessoa(long id, String nome) {
		setId(id);
		setNome(nome);
	}
	
	public Pessoa(Long id, String nome, String telefone1, String email, Usuario usuario, TipoPessoaEnum tipoPessoa){
		
		setId(id);
		setNome(nome);
		setTelefone1(telefone1);
		setEmail(email);
		setUsuario(usuario);
		setTipoPessoa(tipoPessoa);
	}
	
	
	
	/*
	 * Getters and Setters
	 */

	

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getTelefone1() {
		return telefone1;
	}

	public void setTelefone1(String telefone1) {
		this.telefone1 = telefone1;
	}

	public String getTelefone2() {
		return telefone2;
	}

	public void setTelefone2(String telefone2) {
		this.telefone2 = telefone2;
	}

	public boolean isNewsLetter() {
		return newsLetter;
	}

	public void setNewsLetter(boolean newsLetter) {
		this.newsLetter = newsLetter;
	}

	public boolean isAtivo() {
		return ativo;
	}

	public void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}

	public Usuario getUsuario() {
		if (usuario == null) {
			usuario = new Usuario();
//			usuario.setPessoa(this);
		}
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public List<Endereco> getEnderecos() {
		return enderecos;
	}

	public void setEnderecos(List<Endereco> enderecos) {
		this.enderecos = enderecos;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	public TipoPessoaEnum getTipoPessoa() {
		return tipoPessoa;
	}

	public void setTipoPessoa(TipoPessoaEnum tipoPessoa) {
		this.tipoPessoa = tipoPessoa;
	}

	// public Venda getCarrinho() {
	// return carrinho;
	// }
	//
	// public void setCarrinho(Venda carrinho) {
	// this.carrinho = carrinho;
	// }

	
	
	
	@Override
	public String toString() {
		return "Pessoa [id=" + getId() + ", nome=" + nome /* + ", email=" + email
				+ ", telefone1=" + telefone1 + ", telefone2=" + telefone2
				+ ", newsLetter=" + newsLetter + ", ativo=" + ativo
				+ ", usuario=" + usuario + ", endereco=" + enderecos */ + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result
				+ ((enderecos == null) ? 0 : enderecos.hashCode());
		result = prime * result + ((nome == null) ? 0 : nome.hashCode());
		result = prime * result
				+ ((telefone1 == null) ? 0 : telefone1.hashCode());
		result = prime * result
				+ ((telefone2 == null) ? 0 : telefone2.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Pessoa other = (Pessoa) obj;
		if (email == null) {
			if (other.email != null)
				return false;
		} else if (!email.equals(other.email))
			return false;
		if (enderecos == null) {
			if (other.enderecos != null)
				return false;
		} else if (!enderecos.equals(other.enderecos))
			return false;
		if (nome == null) {
			if (other.nome != null)
				return false;
		} else if (!nome.equals(other.nome))
			return false;
		if (telefone1 == null) {
			if (other.telefone1 != null)
				return false;
		} else if (!telefone1.equals(other.telefone1))
			return false;
		if (telefone2 == null) {
			if (other.telefone2 != null)
				return false;
		} else if (!telefone2.equals(other.telefone2))
			return false;
		return true;
	}

	public Interesse getInteresse() {

		if (this.interesse == null) {
			if(this.id == null )
				setInteresse(new Interesse());
			else
				setInteresse(new Interesse(this, new TreeSet<Produto>()));
		}
		return interesse;
	}

	public void setInteresse(Interesse interesse) {
		this.interesse = interesse;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public List<Avaliacao> getAvaliacoes() {
		if( avaliacoes == null)
			setAvaliacoes(new ArrayList<Avaliacao>());
		
		return avaliacoes;
	}

	public void setAvaliacoes(List<Avaliacao> avaliacoes) {
		this.avaliacoes = avaliacoes;
	}

	@Override
	public int compareTo(Pessoa o) {
		return getNome().compareTo(o.getNome());
	}

}